package main

import (
	"context"
	"flag"
	"fmt"
	pb "goGrpcTest/grpcCnf"
	"io"
	"log"
	"net"
	"os"
	"path/filepath"
	"strings"

	"google.golang.org/grpc"
)

var (
	port = flag.Int("port", 50051, "The server port")
)

// server is used to implement helloworld.GreeterServer.
type server struct {
	pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(_ context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
	log.Printf("Received: %v", in.GetName())
	return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil // 获取请求携带的名称直接返回给客户端
}

// UploadFile implements file upload service
func (s *server) UploadFile(stream pb.Greeter_UploadFileServer) error {
	var filename string
	var fileData []byte

	for {
		chunk, err := stream.Recv()
		if err == io.EOF {
			// 接收完成，保存文件
			if filename == "" {
				return stream.SendAndClose(&pb.FileUploadResponse{
					Message:  "Error: no filename provided",
					FileType: "unknown",
					FileSize: 0,
				})
			}

			// 创建上传目录
			uploadDir := "uploads"
			if err := os.MkdirAll(uploadDir, 0755); err != nil {
				return stream.SendAndClose(&pb.FileUploadResponse{
					Message:  fmt.Sprintf("Error creating upload directory: %v", err),
					FileType: "unknown",
					FileSize: 0,
				})
			}

			// 保存文件
			filePath := filepath.Join(uploadDir, filename)
			fmt.Fprintf(os.Stdout, "Saving file: %s\n", filePath)
			if err := os.WriteFile(filePath, fileData, 0644); err != nil {
				return stream.SendAndClose(&pb.FileUploadResponse{
					Message:  fmt.Sprintf("Error saving file: %v", err),
					FileType: "unknown",
					FileSize: 0,
				})
			}

			// 识别文件类型
			fileType := detectFileType(filename, fileData)
			fileSize := int64(len(fileData))

			log.Printf("File uploaded successfully: %s (type: %s, size: %d bytes)", filename, fileType, fileSize)

			return stream.SendAndClose(&pb.FileUploadResponse{
				Message:  fmt.Sprintf("File %s uploaded successfully", filename),
				FileType: fileType,
				FileSize: fileSize,
			})
		}
		if err != nil {
			return err
		}

		if filename == "" {
			filename = chunk.GetFilename()
			// 提取纯文件名，移除路径
			filename = filepath.Base(filename)
		}

		fileData = append(fileData, chunk.GetContent()...)
	}
}

// detectFileType 识别文件类型
func detectFileType(filename string, data []byte) string {
	if len(data) == 0 {
		return "unknown"
	}

	// 通过文件扩展名判断
	ext := strings.ToLower(filepath.Ext(filename))
	switch ext {
	case ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".webp", ".svg":
		return "image"
	case ".mp4", ".avi", ".mov", ".wmv", ".flv", ".mkv", ".webm":
		return "video"
	case ".mp3", ".wav", ".flac", ".aac", ".ogg":
		return "audio"
	case ".pdf":
		return "pdf"
	case ".doc", ".docx":
		return "document"
	case ".xls", ".xlsx":
		return "spreadsheet"
	case ".zip", ".rar", ".7z", ".tar", ".gz":
		return "archive"
	}

	// 通过文件头判断（魔数）
	if len(data) >= 4 {
		header := data[:4]
		// JPEG
		if header[0] == 0xFF && header[1] == 0xD8 {
			return "image"
		}
		// PNG
		if header[0] == 0x89 && header[1] == 0x50 && header[2] == 0x4E && header[3] == 0x47 {
			return "image"
		}
		// GIF
		if header[0] == 0x47 && header[1] == 0x49 && header[2] == 0x46 {
			return "image"
		}
		// PDF
		if header[0] == 0x25 && header[1] == 0x50 && header[2] == 0x44 && header[3] == 0x46 {
			return "pdf"
		}
		// ZIP
		if header[0] == 0x50 && header[1] == 0x4B {
			return "archive"
		}
	}

	return "general"
}

func main() {
	// 参数解析
	flag.Parse()
	// 常见 TCP 链接对象，暂时还未进行 TCP 端口监听
	lis, err := net.Listen("tcp", fmt.Sprintf(":%d", *port))
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	// 创建一个新的 grpc 的 server
	s := grpc.NewServer()
	// 注册 proto中定义的服务Greeter
	pb.RegisterGreeterServer(s, &server{})
	log.Printf("server listening at %v", lis.Addr())
	// 启动 GRPC 服务
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}
